#include "GamePlayScene.h"




GamePlayScene::GamePlayScene(std::string MapPath, std::string QuadTreePath)
{
	_cameraPos.x=0;
	_cameraPos.y=_screenHeight;
	_quadTree = new QuadTree();
	_map = new MarioMap();
	_map->LoadObjectFromFile(MapPath);
	_map->LoadMapFromFile(QuadTreePath);
	_map->Deserialize(_quadTree);

	_mario = new Mario(50, 300, MS_NORMAL); // Chuyen thanh get mario truc tiep tu map
	_infoBar=new InfoBar(0,0,3,0,300);

	//Test Quadtree
	
	collide=false;

	ResourceManager::GetInstance()->GetSound(ResourceManager::GetInstance()->SoundName.BackGround)->Play(true);
}

GamePlayScene::~GamePlayScene()
{
	//delete _mario;
	delete _map;
	delete _quadTree;

	list<Object*>::iterator it;

	for(it=_mapList.begin(); it!=_mapList.end();it++)
	{
		delete (*it);
		*it=0;
	}

	_mapList.clear();

}

void GamePlayScene::_UpdateCamera()
{
	int _mapWidth=_map->GetWidth();
	int _mapHeight=_map->GetHeight();

	D3DXVECTOR2 position;
	position = _mario->GetPosition();
	//_cameraPos.x = position.x - 400;
	//_cameraPos.y = position.y + 300;

	_cameraPos.x= position.x-_screenWidth/2;
	_cameraPos.y=position.y+_screenHeight/2; // Chua tru hao viec ve tu center

	if(_cameraPos.x<0) _cameraPos.x=0;
	else if(_cameraPos.x+_screenWidth>_mapWidth) _cameraPos.x=_mapWidth-_screenWidth;


	//Sua camerapos.y + screenheight thanh` camerapos.y
	if(_cameraPos.y< _screenHeight) _cameraPos.y= _screenHeight;
	else if(_cameraPos.y>_mapHeight) _cameraPos.y=_mapHeight;

}
//
//void GameRunScene::Create()
//{
//}



void GamePlayScene::Update(float DeltaTime)
{
//// Clip view
	RECT viewRect;
	viewRect.left = _cameraPos.x;
	viewRect.top = _cameraPos.y;
	viewRect.right = viewRect.left + _screenWidth;
	viewRect.bottom = viewRect.top - _screenHeight;
	Object* obj;
	list<Object*>::iterator i;
	for (i = _mapList.begin(); i != _mapList.end(); i++)
	{
		obj = *i;
	}
	_mapList.clear();

	_quadTree->getObjectFromCamara(viewRect, &_mapList);
	//// Di chuyen Mario
	_mario->Update(&_mapList,DeltaTime);

	// Update Camera
	_UpdateCamera();

	// Update tat ca object con lai
	for (i = _mapList.begin(); i != _mapList.end(); i++)
	{
		obj = *i;
		obj->Update(&_mapList,DeltaTime );
	}

	/*if(_mario->bullet!=NULL)
	{
		_mario->bullet->Update(&_mapList, DeltaTime);
	}
	if(_mario->bullet2!=NULL)
	{
		_mario->bullet2->Update(&_mapList, DeltaTime);
	} */

	_infoBar->Update();
	_ProcessInput();
	
}

void GamePlayScene::Render()
{
	ResourceManager::GetInstance()->GetSurface(ResourceManager::GetInstance()->SurfaceName.BackgroundTest)->Draw(_backBuffer, NULL, NULL );
	Object * _obj;
	list<Object *>::iterator k;
	for (k = _mapList.begin(); k !=_mapList.end(); k++)
	{
		_obj =*k;
		_obj->Render(_cameraPos.x, _cameraPos.y);
	}

	
	/*_spriteHandler->Begin(D3DXSPRITE_ALPHABLEND);*/
	/*for(int i = 0;i<_list.size(); i++)
	{
		for (int j = 0; j < _mapList.size(); j++)
		{
			if(_list[i] == _mapList[j]->_id)
			{
				_mapList[j]->Render(_cameraPos.x, _cameraPos.y);
			}
		}
	}*/
	_mario->Render(_cameraPos.x,_cameraPos.y);
	
	
	if(_mario->bullet!=NULL)
	{
		_mario->bullet->Render(_cameraPos.x,_cameraPos.y);
	}
	if(_mario->bullet!=NULL)
	{
		_mario->bullet2->Render(_cameraPos.x,_cameraPos.y);
	}
	_infoBar->Render();
	/*_spriteHandler->End();*/
}

void GamePlayScene::Leave()
{
	// Giai phong bo nho
	//delete _mario;
	delete _map;
	delete _quadTree;

	list<Object*>::iterator it;

	for(it=_mapList.begin(); it!=_mapList.end();it++)
	{
		delete (*it);
		*it=0;
	}

	_mapList.clear();

	ResourceManager::GetInstance()->GetSound(ResourceManager::GetInstance()->SoundName.BackGround)->Stop();
	
}

void GamePlayScene::Pause()
{
	// Tam thoi ngung hoat dong
	ResourceManager::GetInstance()->GetSound(ResourceManager::GetInstance()->SoundName.BackGround)->Stop();
}

void GamePlayScene::Resume()
{
	// Tai hoat dong
	ResourceManager::GetInstance()->GetSound(ResourceManager::GetInstance()->SoundName.BackGround)->Play(true);
}

void GamePlayScene::_ProcessInput()
{
	//Dieu khien nhay
	_OnKeyDown(0);
	//State
	//Nhan phim va giu
	if (CGame::GetInstance()->GetInput()->IsKeyDown(DIK_RIGHT))
	{
		/*if(collide==false)
			_mario->TurnRight();
		else
		{
			_mario->_vx=0;
			//_mario->_vy=0;
			//_mario->_x -= 2;
			collide=false;
		}*/
		
		_mario->TurnRight();
		
	}	
	else if (CGame::GetInstance()->GetInput()->IsKeyDown(DIK_LEFT))
	{
		/*if(collide==false)
			_mario->TurnLeft();
		else
			{
				_mario->_x += 20;
				_mario->_vx=0;
				//_mario->_vy=0;
				
				collide = false;

			}
			*/
		_mario->TurnLeft();
	}
	else if(CGame::GetInstance()->GetInput()->IsKeyDown(DIK_P))
	{
		ResourceManager::GetInstance()->GetSound(ResourceManager::GetInstance()->SoundName.Pause)->Play(false);
		SceneManager::GetInstance()->PushScene((Scene*)new PauseScene());	
		
	}
	else if(CGame::GetInstance()->GetInput()->IsKeyDown(DIK_K))
	{
		SceneManager::GetInstance()->PushScene((Scene*)new GameOverScene());
	}
	else if(CGame::GetInstance()->GetInput()->IsKeyDown(DIK_S))
	{
		_mario->Shoot();
	}
	else
	{
		//if(collide==false)
		//	_mario->Reset();
		//else
		//{
		//	_mario->_vx=0;
		//	_mario->_vy=0;
		//}

		_mario->Reset();
		
	}
	
}

void GamePlayScene::_OnKeyDown(int KeyCode)
{
	int temp = CGame::GetInstance()->GetInput()->GetKeyDown();
	switch (temp)
	{
		case DIK_SPACE:
			_mario->Jump();

			break;

		case DIK_UP:
			_mario->Jump();

			break;
	}
}

void GamePlayScene::_OnKeyUp(int KeyCode)
{
	int temp = CGame::GetInstance()->GetInput()->GetKeyUp();
	switch (KeyCode)
	{
		case DIK_SPACE:
			 
			break;
	}
}

/*bool GamePlayScene::_AABBCheck(Box b1, Box b2)
{
	return !(b1.x + b1.w < b2.x || b1.x > b2.x + b2.w || b1.y + b1.h < b2.y || b1.y > b2.y + b2.h);
}

bool GamePlayScene::_AABB(Box b1, Box b2, float& moveX, float& moveY)
{
	moveX = moveY = 0.0f;

    float l = b2.x - ( b1.x + b1.w );
    float r = ( b2.x + b2.w ) - b1.x;
    float t = b2.y - ( b1.y + b1.h );
    float b = ( b2.y + b2.h ) - b1.y;
	
	// check that there was a collision
    if (l > 0 || r < 0 || t > 0 || b < 0)
        return false;

	// find the offset of both sides
    moveX = abs(l) < r ? l : r;
    moveY = abs(t) < b ? t : b;

	// only use whichever offset is the smallest
    if (abs(moveX) < abs(moveY))
        moveY = 0.0f;
    else
        moveX = 0.0f;

    return true;
}

Box GamePlayScene::_GetSweptBroadphaseBox(Box b)
{
	Box broadphasebox(0.0f, 0.0f, 0.0f, 0.0f);

    broadphasebox.x = b.vx > 0 ? b.x : b.x + b.vx;
    broadphasebox.y = b.vy > 0 ? b.y : b.y + b.vy;
    broadphasebox.w = b.vx > 0 ? b.vx + b.w : b.w - b.vx;
    broadphasebox.h = b.vy > 0 ? b.vy + b.h : b.h - b.vy;

    return broadphasebox;
}

float GamePlayScene::_SweptAABB(Box b1, Box b2, float* normalx, float* normaly, float deltatime)
{
	float xInvEntry, yInvEntry;
    float xInvExit, yInvExit;

    // find the distance between the objects on the near and far sides for both x and y
    if (b1.vx > 0.0f)
    {
		xInvEntry = b2.x - (b1.x + b1.w);
        xInvExit = (b2.x + b2.w) - b1.x;
 
    }
    else 
    {
		xInvEntry = (b2.x + b2.w) - b1.x;
		xInvExit = b2.x - (b1.x + b1.w);
		//xInvEntry=b1.x-(b2.x+b2.w);
		//xInvExit=b1.x+b1.w-b2.x;

    }

    if (b1.vy > 0.0f)
    {
		yInvEntry = b2.y - (b1.y + b1.h);
		yInvExit = b2.y + b2.h - b1.y;


    }
    else
    {
        yInvEntry = (b2.y + b2.h) - b1.y;
        yInvExit = b2.y - (b1.y + b1.h);
		//yInvEntry=b1.y-(b2.y+b2.h);
		//yInvExit=b1.y+b1.h-b2.y;
    }
	
    // find time of collision and time of leaving for each axis (if statement is to prevent divide by zero)
    float xEntry, yEntry;
    float xExit, yExit;

    if (b1.vx == 0.0f)
    {
        xEntry = -std::numeric_limits<float>::infinity();
        xExit = std::numeric_limits<float>::infinity();
    }
    else
    {
        xEntry = xInvEntry / b1.vx;
        xExit = xInvExit / b1.vx;
    }

    if (b1.vy == 0.0f)
    {
        yEntry = -std::numeric_limits<float>::infinity();
        yExit = std::numeric_limits<float>::infinity();
    }
    else
    {
		yEntry = yInvEntry / b1.vy;
        yExit = yInvExit / b1.vy;
    }
	
    // find the earliest/latest times of collision
	float entryTime = max(xEntry, yEntry);
    float exitTime = min(xExit,yExit);
	
    // if there was no collision ( khi dat vx = 0, xay ra va cham nhung xEntry va yEntry << 0 => xet la ko va cham)
    //if ((entryTime > exitTime) || (xEntry < 0.0f && yEntry < 0.0f) || (xEntry > 1.0f && yEntry > 1.0f))  
	if ((entryTime > exitTime) || (xEntry > 1.0f && yEntry > 1.0f))  
    {
        *normalx = 0.0f;
        *normaly = 0.0f;
        return 1.0f;
    }
    else // if there was a collision
    {        		
        // calculate normal of collided surface
        if (xEntry > yEntry)
        {
            if (xInvEntry < 0.0f)
            {
                *normalx = 1.0f;  // <======
                *normaly = 0.0f;
            }
	        else
            {
                *normalx = -1.0f; // =====>
                *normaly = 0.0f;
            }
        }
        else
        {
            if (yInvEntry < 0.0f)
            {
				*normalx = 0.0f;  // di xuong
                *normaly = 1.0f;
            }
	        else
            {
                *normalx = 0.0f;  // di len
		        *normaly = -1.0f;
            }
        }

        // return the time of collision
        return entryTime;
    }
}*/